r"""
_do_cmp() from 'C:\Users\mdsy\AppData\Local\Programs\Python\Python36-32\Lib\filecmp.py'
does not return index of mismatch, so here we go:
"""
import os,sys #,filecmp
import argparse

def get_parser():
    parser = argparse.ArgumentParser(description='Compare binary files')
    parser.add_argument('file1')
    parser.add_argument('file2')
    #parser.add_argument('query', metavar='QUERY', type=str, nargs='*', help='the question to answer')
    parser.add_argument('-b','--buffer', help='select buffer size [KB] (default= 8)', default=8, type=int)
    parser.add_argument('-q','--quick', help='perform quick compare (reliable only if it reports mismatch)', action='store_true')
    parser.add_argument('-v','--verbose', help='display comparison bytes', action='store_true')
    argp = parser.parse_args()
    return argp

print()

argp = get_parser()

file1 = argp.file1
file2 = argp.file2
quick = argp.quick
verbose = argp.verbose
bufsize_multiple = abs(argp.buffer) or 1
#sys.exit()


def _do_quick_cmp(f1, f2):
    """compare 100 aprox. bytes only"""
    COMPARE_COUNT = 100
    BUFSIZE = 1
    with open(f1, 'rb') as fp1:
        length1 = fp1.seek(0, 2)
    if length1 > COMPARE_COUNT:
        step = length1 // COMPARE_COUNT
    else:
        step = 1

    with open(f1, 'rb') as fp1, open(f2, 'rb') as fp2:
        pos = 0
        count = 0
        while pos < length1:
            count += 1
            b1 = fp1.read(BUFSIZE)
            b2 = fp2.read(BUFSIZE)
            if verbose:
                print("{0:>4}--> {1:>08X}:  {2:02X} {4} {3}".format(count, pos, ord(b1), b2.hex(), "==" if b1==b2 else "<>"))
            if b1 != b2:
                #//Console.WriteLine("files are different");
                return False
            pos += step
            fp1.seek(pos, 0)
            fp2.seek(pos, 0)
    return True

def _do_full_cmp(f1, f2):
    bufsize = bufsize_multiple * 1024
    #bufsize = bufsize or 1024
    print(bufsize)
    with open(f1, 'rb') as fp1, open(f2, 'rb') as fp2:
        while True:
            b1 = fp1.read(bufsize)
            b2 = fp2.read(bufsize)
            #print(len(b1))
            if b1 != b2:
                for i,_ in enumerate(b1):
                    if b1[i] != b2[i]:
                        offset = i
                        break
                #print(dir(fp1))
                pos = fp1.tell() - len(b1) + offset
                print( "\n\tFirst-found mismatch at offset 0x%X :   0x%X <> 0x%X" % (pos, b1[i], b2[i]) )
                return False
            if not b1:
                return True

#matching = filecmp.cmp(file1, file2, shallow = False)
size1 = os.stat(file1).st_size
size2 = os.stat(file2).st_size
if size1 != size2:
    print("\n\tFiles have different sizes.")
else:
    matching = _do_quick_cmp(file1, file2)
    # _do_quick_cmp() is reliable only when it finds that the 2 files are different,
    # so if it returns true it might be a false positive, so we do a full comparsion
    if matching and not quick:
        print("\n\tThe files SEEM to match, let's make sure...")
        matching = _do_full_cmp(file1, file2)
    print("\n\tFiles match." if matching else "\n\tFiles are different!")
